-
Notifications
You must be signed in to change notification settings - Fork 26
feat: keep form data in memory #1525
base: main
Are you sure you want to change the base?
feat: keep form data in memory #1525
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements form data persistence in memory to maintain user-entered data across tab switches and route navigation. The implementation includes tab mounting behavior changes and form state management for cross-route drafts.
- Added
FormPersistenceStateprovider for managing in-memory form drafts across routes - Modified
Tabscomponent to supportkeepMountedprop for preserving tab content in DOM - Enhanced
FeeModalto preselect fee rate options based on current fee rate
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ui/common/state/index.tsx | Added FormPersistenceState to the state provider list |
| src/ui/common/state/FormPersistenceState.tsx | New state provider for managing BTC and Baby stake form drafts |
| src/ui/common/page.tsx | Enabled keepMounted prop for main tabs |
| src/ui/common/components/Tabs/Tabs.tsx | Added keepMounted functionality to preserve tab content |
| src/ui/common/components/Staking/FeeModal/index.tsx | Added currentFeeRate prop and preselection logic |
| src/ui/common/components/Multistaking/MultistakingForm/StakingFeesSection.tsx | Removed redundant default fee rate setting and passed currentFeeRate to FeeModal |
| src/ui/common/components/Multistaking/MultistakingForm/MultistakingFormContent.tsx | Added BtcFormPersistence component |
| src/ui/common/components/Multistaking/MultistakingForm/BtcFormPersistence.tsx | New component for persisting BTC staking form data |
| src/ui/baby/widgets/StakingForm/index.tsx | Added BabyFormPersistence component |
| src/ui/baby/widgets/StakingForm/BabyFormPersistence.tsx | New component for persisting Baby staking form data |
| src/ui/baby/layout.tsx | Enabled keepMounted prop for baby staking tabs |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| stakingInfo?.defaultFeeRate !== undefined && | ||
| (feeRate === undefined || feeRate === "") |
Copilot
AI
Sep 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The condition feeRate === \"\" should use a more robust check. Consider using a utility function to check for empty/falsy values consistently across the codebase, or at minimum check for both \"\" and \"0\".
| stakingInfo?.defaultFeeRate !== undefined && | |
| (feeRate === undefined || feeRate === "") | |
| (feeRate === undefined || feeRate === "" || feeRate === "0") |
| const fee = Number(currentFeeRate); | ||
| if (!fee || !Number.isFinite(fee)) { |
Copilot
AI
Sep 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition !fee will be true for valid fee rate of 0, which should be allowed. Change to !Number.isFinite(fee) || fee <= 0 to properly handle zero values while rejecting invalid numbers.
| const fee = Number(currentFeeRate); | |
| if (!fee || !Number.isFinite(fee)) { | |
| if (!Number.isFinite(fee) || fee < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved with some comments, let's wait for @jonybur and @jeremy-babylonlabs also
| if (babyStakeDraft) { | ||
| if (babyStakeDraft.amount !== undefined) { | ||
| setValue("amount", babyStakeDraft.amount, { | ||
| shouldValidate: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have comments on these values so it's easier to understand why, besides Hydrate once on mount
| if (btcStakeDraft) { | ||
| if (btcStakeDraft.finalityProviders) { | ||
| setValue("finalityProviders", btcStakeDraft.finalityProviders, { | ||
| shouldValidate: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
|
|
||
| import { createStateUtils } from "@/ui/common/utils/createStateUtils"; | ||
|
|
||
| export type BtcStakeDraft = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add comments for these types and interfaces
| } | ||
| if (babyStakeDraft.feeAmount !== undefined) { | ||
| setValue("feeAmount", babyStakeDraft.feeAmount, { | ||
| shouldValidate: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could probably move these {shouldValidate: true, shouldDirty: false, shouldTouch: false} to a const and assign on each of these setValues. Would make the code a bit cleaner.
Actually, since we are at it, this is simply a matter of doing something like
["amount", "validatorAddress", "feeAmount"].forEach(value => {
if (babyStakeDraft[value] !== undefined) setValue(value, /*object here*/)
}
| className="flex flex-col gap-2 h-[500px]" | ||
| onSubmit={handlePreview} | ||
| > | ||
| <BabyFormPersistence /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a functional component? can't this be a hook instead? Since it's returning null that is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree
Added
keepMountedtoTabsAdded
FormPersistenceStateprovider that wraps app for cross-route in-memory draftsFeeModalnow takescurrentFeeRateand preselects fast/medium/slow/customScreen.Recording.2025-09-02.at.16.20.15.mov
Closes: #1403